package cn.jobstart.es.service;

import cn.jobstart.common.BeanUtils;
import cn.jobstart.common.IdGen;
import cn.jobstart.common.StringUtil;
import cn.jobstart.es.listener.event.EsEvent;
import cn.jobstart.es.model.AbstractEsModel;
import cn.jobstart.pubInter.exception.BusinessException;
import cn.jobstart.pubInter.exception.DaoExceptionEnum;
import cn.jobstart.pubInter.exception.SkException;
import org.apache.poi.ss.formula.functions.T;
import org.dromara.easyes.core.biz.EntityInfo;
import org.dromara.easyes.core.biz.EsPageInfo;
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.dromara.easyes.core.core.BaseEsMapper;
import org.dromara.easyes.core.toolkit.EntityInfoHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;

import java.lang.reflect.ParameterizedType;
import java.util.List;

/**
 * @author sunke
 * @version 1.0
 * @Description
 * @date 2023-09-22 11:25
 */
public abstract class AbstractEsService<E extends AbstractEsModel, ESearch extends LambdaEsQueryWrapper<E>, EM extends BaseEsMapper<E>> {


    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;


    public abstract EM getMapper();


    /**
     * 创建索引
     *
     * @return
     */
    public boolean createIndex() throws SkException {

        EntityInfo entityInfo = EntityInfoHelper.getEntityInfo(getMapper().getEntityClass());

        if (!getMapper().existsIndex(entityInfo.getIndexName())) {
            return getMapper().createIndex().booleanValue();
        }
        return false;

    }

    /**
     * 删除索引
     *
     * @return
     */
    public boolean deleteIndex() throws SkException {

        EntityInfo entityInfo = EntityInfoHelper.getEntityInfo(getMapper().getEntityClass());
        if (getMapper().existsIndex(entityInfo.getIndexName())) {
            return getMapper().deleteIndex(entityInfo.getIndexName()).booleanValue();
        }
        return false;

    }


    public void beforePublishEvent(EsEvent event) throws SkException {

    }


    public void afterPublishEvent(EsEvent event) throws SkException {

    }


    public void publishEvent(EsEvent event) throws SkException {
        beforePublishEvent(event);
        applicationEventPublisher.publishEvent(event);
        afterPublishEvent(event);

    }


    public void beforeSelectList(ESearch eSearch) throws SkException {
        beforeSearch(eSearch);
    }

    public void afterSelectList(ESearch eSearch, List<E> resultList) throws SkException {

    }


    public List<E> selectList(ESearch eSearch) throws SkException {

        try {

            if (StringUtil.isNullOrEmpty(eSearch)) {
                eSearch = getSearchClass().newInstance();
            }
            beforeSelectList(eSearch);

            List<E> resultList = getMapper().selectList(eSearch);

            afterSelectList(eSearch, resultList);

            return resultList;
        } catch (InstantiationException e) {

        } catch (IllegalAccessException e) {

        }
        return null;
    }


    public Class<E> getDomainClass() {
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        return (Class) type.getActualTypeArguments()[0];
    }

    /**
     * 返回搜索类Class
     *
     * @return
     */
    public Class<ESearch> getSearchClass() {
        ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
        return (Class) type.getActualTypeArguments()[1];
    }


    public void beforeDetail(String id) throws SkException {

    }

    public void afterDetail(String id, E e) throws SkException {

    }

    /**
     * 详情
     *
     * @param id
     * @return
     * @throws SkException
     */

    public E detailById(String id) throws SkException {
        beforeDetail(id);
        if (StringUtil.isNullOrEmpty(id)) {
            return null;
        }
        E domain = getMapper().selectById(id);
        afterDetail(id, domain);

        return domain;
    }


    public void beforeInsert(E domain) throws SkException {

    }

    public void afterInsert(E domain) throws SkException {

    }


    /**
     * 添加
     *
     * @param domain
     * @return
     * @throws SkException
     */

    public E insert(E domain) throws SkException {
        beforeInsert(domain);
        if (StringUtil.isNullOrEmpty(domain)) {
            return domain;
        }
        /*if (StringUtil.isNullOrEmpty(domain.getId())) {
            domain.setId(IdGen.uuid());
        }*/

        int result = getMapper().insert(domain);
        if (result == 0) {
            throw new BusinessException(DaoExceptionEnum.DAO_INSERT_ERROR);
        }
        afterInsert(domain);
        return domain;
    }


    public void beforeUpdate(E domain) throws SkException {

    }

    public void afterUpdate(E domain, E updateDomain) throws SkException {

    }

    /**
     * 更新
     *
     * @param domain
     * @return
     * @throws SkException
     */

    public E update(E domain,String id) throws SkException {
        beforeUpdate(domain);

       // String id = domain.getId();

        E old = detailById(id);
        if (StringUtil.isNullOrEmpty(old)) {
            return null;
        }
        BeanUtils.copyPropertiesIgnoreNull(domain, old);
        int result = getMapper().updateById(old);
        if (result == 0) {
            throw new BusinessException(DaoExceptionEnum.DAO_UPDATE_ERROR);
        }

        afterUpdate(domain, old);
        return old;
    }

    /**
     * 删除
     *
     * @param id
     * @return
     * @throws SkException
     */

    public int delete(String id) throws SkException {
        beforeDelete(id);
        if (StringUtil.isNullOrEmpty(id)) {
            return 0;
        }
        int result = getMapper().deleteById(id);
        afterDelete(id, result);
        return result;
    }

    public void beforeDelete(String id) throws SkException {

    }

    public void afterDelete(String id, int result) throws SkException {

    }


    public void beforeSearch(ESearch search) throws SkException {

    }


    public void beforePageQuery(ESearch search, int pageNum, int pageSize) throws SkException {
        beforeSearch(search);
    }

    public void afterPageQuery(ESearch search, int pageNum, int pageSize, EsPageInfo<E> pageInfo) throws SkException {

    }


    /**
     * 查询
     *
     * @param search
     * @param pageNum
     * @param pageSize
     * @return
     * @throws SkException
     */

    public EsPageInfo<E> pageQuery(ESearch search, int pageNum, int pageSize) throws SkException {
        beforePageQuery(search, pageNum, pageSize);


        EsPageInfo esPageInfo = getMapper().pageQuery(search, pageNum, pageSize);

        afterPageQuery(search, pageNum, pageSize, esPageInfo);
        return esPageInfo;
    }







    public void beforeCount(ESearch eSearch) throws SkException {
        beforeSearch(eSearch);
    }

    public void afterCount(ESearch eSearch, long result) throws SkException {

    }

    /**
     * 查询条数
     *
     * @param eSearch
     * @return
     */

    public long getCountBySearch(ESearch eSearch) throws SkException {
        beforeCount(eSearch);
        long result = getMapper().selectCount(eSearch);
        afterCount(eSearch, result);
        return result;


    }
}
